package bch.rocketmq.consumer;

import bch.rocketmq.util.SnowflakeWorker;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.aop.framework.AopContext;
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;

@RocketMQTransactionListener
@Component
@Slf4j
public class MyTransactionListener implements RocketMQLocalTransactionListener {
    @Resource
    private JdbcClient jdbcClient;
    /**
     * executeLocalTransaction 在发送半消息后执行本地事务，并直接返回事务状态。
     * checkLocalTransaction 则是 Broker 在未收到明确事务结果时调用，用来主动查询本地事务的最终状态
     */

    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        // 执行本地事务逻辑
        // 返回 COMMIT, ROLLBACK 或 UNKNOWN
        log.info("executeLocalTransaction msg:{}, arg:{}", msg, arg);
        try {
            // 这里写你的本地事务逻辑，例如扣减库存、插入订单
            ((MyTransactionListener) AopContext.currentProxy()).doBusiness();
            return RocketMQLocalTransactionState.COMMIT;
        } catch (Exception e) {
            // 这里的 catch 只是为了告诉 RocketMQ “要丢弃半消息”，而不是拦截事务回滚。
            // 因为 Spring 已经在抛异常的那一刻完成了回滚
            // 一会儿会checkLocalTransaction来检查事务状态，这里可以捕获异常，并返回UNKNOWN
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    // 其实如果把一组数据库操作和mq操作bind
    // 某个请求有n组这种操作 那么其实就是n个事务
    // 根本做不到(嵌套RocketMQLocalTransactionListener 可以做到 但是根本没必要)
    @Transactional(rollbackFor = Exception.class)
    public void doBusiness() {
        boolean synchronizationActive = TransactionSynchronizationManager.isSynchronizationActive();
        int rows = jdbcClient.sql("insert into company (id, name) values(?, ?)")
                .params(SnowflakeWorker.newId(), "Baidu")
                .update();
        int i = 1 / 0;
        // 这里再发事务消息 通过LocalTransactionState来回滚当前事务/半消息
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        // 检查本地事务状态
        log.info("checkLocalTransaction msg:{}", msg);
        boolean confirm = checkBusiness(msg);
        return confirm ? RocketMQLocalTransactionState.COMMIT : RocketMQLocalTransactionState.ROLLBACK;
    }

    private boolean checkBusiness(Message msg) {
        return true;
    }
}
